﻿


using IotClientService.Enums;
using IotClientService.Handles.hks;
using IotContract.Dtos.Clients.Equips;
using IotContract.Events;
using IotContract.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using XT.Common.Extensions;

namespace IotClientService.Handles;
public class HkSelTcpHandle
{
    public event EventHandler<ConnectStatusEventArgs> OnConnectLogChanged;

    private ConnectTypeEnum _connectType;

    private TcpClient equipComm;

    private HkSelEquipDto _group;

    private NetworkStream equipCommStream;

    public int plcCount = 101;

    public int PLC_COMM_MODE;

    public int DR_WordS;

    public int DR_WordE;

    public int DW_WordS;

    public int DW_WordE;

    public int DBUFF_OFFSET;

    public byte DEVICE_CODE;

    public CnvVariable CnvC;

    public int CnvCommOK;

    public int ErrorCount = 0;

    private IConnectDataService _connectDataService;
    private HkSelEquipDto _selEquipDto;
    private bool _curConnection = false;

    public HkSelTcpHandle()
    {
        this.equipComm = new TcpClient();
        this.equipCommStream = null;
        
    }


    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="connectDataService"></param>
    /// <returns></returns>
    public bool Init(IConnectDataService connectDataService, HkSelEquipDto equip)
    {
        _connectDataService = connectDataService;
        _selEquipDto = equip;

        this.CnvC = new CnvVariable();
        this.CnvCommOK = 0;
        this.PLC_COMM_MODE = 0;
        this.DR_WordS = 0;
        this.DR_WordE = 0;
        this.DW_WordS = 0;
        this.DW_WordE = 0;
        this.DBUFF_OFFSET = 0;
        this.DEVICE_CODE = 0;
        this.PLC_COMM_MODE = 1;
        this.DR_WordS = 0;
        this.DR_WordE = 650;
        this.DW_WordS = 0;
        this.DW_WordE = 0;
        this.DBUFF_OFFSET = 10000;
        this.DEVICE_CODE = 176;
        return true;
    }

    public bool ConnectServer(HkSelEquipDto group)
    {
        if (_connectType == ConnectTypeEnum.Connecting) return false;
        _group = group;

        // 解析ipaddress
        var ips = group.IPAddress.Split(":");
        if (ips.Length != 2)
        {
            return false;
        }
        string hostIP = ips[0];
        int hostPort = ips[1].To<int>();

        

        try
        {
            _connectType = ConnectTypeEnum.Connecting;
            //hostIP = "localhost";
            this.equipComm = new TcpClient(hostIP, hostPort)
            {
                ReceiveTimeout = 50,
                SendTimeout = 50
            };
            this.equipCommStream = this.equipComm.GetStream();
            _group.ReadTime = DateTime.Now;

            _group.Value = "";
           _curConnection = true;

            OnConnectLogChanged?.Invoke(this, new ConnectStatusEventArgs
            {
                Connect = true,
                IsSuccess=true

            });
            _connectType = ConnectTypeEnum.Connected;
        }
        catch (Exception exception1)
        {

            Exception exception = exception1;
            _group.ReadTime = DateTime.Now;
            _group.Value = exception.Message;

            _connectType = ConnectTypeEnum.Stop;

            OnConnectLogChanged?.Invoke(this, new ConnectStatusEventArgs
            {
                Connect = false,
                IsSuccess = false,
                Message = exception1.Message
            }); 
            Thread.Sleep(1);

            return false;
        }

        return true;


    }



    
  

    public async Task<byte[]> PlcRead()
    {
        byte[] numArray = null;
        try
        {
            //this.GetTcpConnections();
            if (this.equipCommStream != null && this.equipCommStream.CanRead)
            {
                byte[] numArray1 = new byte[1119];
                int num = 0;
                do
                {
                    num = await this.equipCommStream.ReadAsync(numArray1, 0, (int)numArray1.Length);
                }
                while (this.equipCommStream.DataAvailable);
                if (num != 0)
                {
                    byte[] numArray2 = new byte[num];
                    Array.Copy(numArray1, numArray2, num);
                    numArray = numArray2;
                    return numArray;
                }
            }
            ErrorCount = 0;
        }
        catch (SocketException socketException)
        {
            OnConnectLogChanged?.Invoke(this, new ConnectStatusEventArgs
            {
                Connect = false,
              
                Message = socketException.Message
            });

        }
        catch (Exception exception)
        {

            ErrorCount++;

        }

        return numArray;




    }

    public void PlcWrite(byte[] txBuffB, int txcnt)
    {
        this.equipCommStream?.Write(txBuffB, 0, txcnt);
    }

    public bool GetConnection()
    {
        try
        {
            if (equipComm == null || this.equipCommStream == null) return false;
            // 

            if (equipComm == null || equipComm.Connected == false || equipComm.Client.Poll(1, SelectMode.SelectRead) == true && equipComm.Available == 0
                      )
            {
                return false;
            }
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }

    }

    public async Task RecieveData()
    {
        if (this.GetConnection())
        {
            var data = await PlcRead();
            CnvC.RxBuffB = data;
            if (data != null)
            {
                CnvC.RxCnt = (int)CnvC.RxBuffB.Length;
                CnvC.RxEnd = 1;
                _group.ReadTime = DateTime.Now;
            }
        }
    }

    public void DisconnectServer()
    {
        try
        {
            if(this.equipCommStream?.Socket.Connected==true)
            this.equipCommStream?.Close();
            if(this.equipComm?.Connected==true)
            this.equipComm?.Close();
            _curConnection = false;

        }
        catch (Exception exception)
        {
            OnConnectLogChanged?.Invoke(this, new ConnectStatusEventArgs
            {
                Connect = false,
                Message = exception.Message,
               

            });
        }
    }
}
